`include "../include/cpu_defines.sv"
`include "../include/common.sv"

module BarrierController(
	input logic cpu_clk,
	input logic cpu_rst_n,
	input logic inst_data_ok,
	input logic data_data_ok,
	input logic inst_addr_ok,
	input logic data_addr_ok,
	input logic inst_buffer_ok,
	input logic predict_clear,
	input logic branch_predict_fail,
	input logic rat_stall,
	input logic dis_stall,
	input logic branch_fail,
	output logic [`STAGE_SIZE-1: 0] ready,// 1 is open 
	output logic [`STAGE_SIZE-1: 0] clear,
	output logic flush
);

	assign flush = branch_fail;
	logic branch_fail_stall;

	always_ff @(posedge cpu_clk)begin
		if(cpu_rst_n == 1'b0)begin
			branch_fail_stall <= 1'b0;
		end
		else begin
			if(branch_predict_fail)begin
				branch_fail_stall <= 1'b1;
			end
			if(branch_fail)begin
				branch_fail_stall <= 1'b0;
			end
		end
	end

	always_comb begin
		if(cpu_rst_n == `RST_ENABLE)
		begin
			ready = `LSHIFTX(`STAGE_SIZE)-1;
			clear = `LSHIFTX(`STAGE_SIZE)-1;
		end
		else begin
			ready[0] = inst_addr_ok && inst_buffer_ok && !branch_fail_stall ? 1'b1 : 1'b0;
			ready[1] = inst_data_ok ? 1'b1 : 1'b0; // IF-ID
			ready[2] = rat_stall | dis_stall; // ID-RAT
			ready[3] = dis_stall; // RAT-DIS
			ready[4] = 1'b1;

			clear[0] = predict_clear;
			clear[1] = predict_clear;
			clear[2] = flush;
			clear[3] = rat_stall ? 1'b1 : 1'b0;
			clear[4] = 1'b0;
		end
	end
endmodule